package com.easyaop.api.join;

import com.easyaop.commons.MethodSignature;
import com.easyaop.commons.utils.PointcutUtils;
import com.easyaop.commons.utils.ReflectUtils;

import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.util.function.BiFunction;

/**
 * @author lipan
 * @since 2025-03-07
 */
abstract class AbstractJoinPoint {
    private static final WeakCache<ClassLoader, String, Method> CACHE = new WeakCache<>(new KeyFactory(),
            new ValueFactory());

    protected Method getMethod(ClassLoader classLoader, String signature) {
        return CACHE.get(classLoader, signature);
    }

    protected static class KeyFactory implements BiFunction<ClassLoader, String, Object> {
        @Override
        public Object apply(ClassLoader classLoader, String signature) {
            return signature;
        }
    }

    protected static class ValueFactory implements BiFunction<ClassLoader, String, Method> {
        @Override
        public Method apply(ClassLoader classLoader, String signature) {
            Class<?> clazz = PointcutUtils.parseClass(classLoader, signature);
            MethodSignature methodSignature = PointcutUtils.parseMethodSignature(signature);
            MethodType methodType = MethodType.fromMethodDescriptorString(methodSignature.getDescriptor(),
                    classLoader);
            return ReflectUtils.findDeclaredMethod(clazz, methodSignature.getName(), methodType.parameterArray());
        }
    }
}
